#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstdlib>
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;


void handler(int signo)
{
    cout << "我是一个进程，刚刚获取了一个信息：" << signo << endl;
}

// 打印当前信号集中的信号
void printPending(sigset_t *pending)
{
    for (int sig = 1; sig <= 31; ++sig)
    {
        if (sigismember(pending, sig))
            cout << "1";
        else
            cout << "0";
    }
    cout << endl;
}

int main()
{
    cout << "pid:" << getpid() << endl;

    // 屏蔽2号和5号信号
    sigset_t set, oset;
    sigemptyset(&set);
    sigemptyset(&oset);
    // sigfillset();
    for (int sig = 1; sig <= 31; sig++)
    {
        // 将2号和5号信号添加到信号屏蔽字中
        sigaddset(&set, 2);
        sigaddset(&set, 5);
        // signal
        signal(sig, handler);
    }
    // 设置用户级的信号屏蔽字到内核中
    sigprocmask(SIG_SETMASK, &set, &oset);

    // 不断获取当前进程的pending信号集
    sigset_t pending;
    int count = 0;
    while (true)
    {
        // 清空信号集
        sigemptyset(&pending);
        // 获取当前进程的pending信号集
        if (sigpending(&pending) == 0)
        {
            // 打印一个当前进程的pending信号集
            printPending(&pending);
        }
        sleep(1);
        count++;
        if (count == 20)
        {
            cout << "解除对所有信号的block..." << endl;
            sigemptyset(&set);
            sigprocmask(SIG_SETMASK, &set, nullptr);
        }
    }
    return 0;
}

// // 打印当前信号集中的信号
// void printPending(sigset_t *pending)
// {
//     for (int i = 1; i <= 31; ++i)
//     {
//         if (sigismember(pending, i))
//             cout << "1";
//         else
//             cout << "0";
//     }
//     cout << endl;
// }

// int main()
// {
//     cout << "pid:" << getpid() << endl;
//     sigset_t set, oset;
//     sigemptyset(&set); // 初始化信号集
//     sigemptyset(&oset);

//     sigaddset(&set, 2);                    // 向信号集中添加2号信号SIGINT
//     sigaddset(&set, 5);                    // 向信号集中添加5号信号SIGINT
//     sigprocmask(SIG_SETMASK, &set, &oset); // 设置用户级的信号屏蔽字到内核中，让当前的进行将2号和5号信号屏蔽

//     sigset_t pending;
//     sigemptyset(&pending);

//     while (1)
//     {
//         sigpending(&pending);
//         printPending(&pending);
//         sleep(1);
//     }
//     return 0;
// }

// int count = 0;
// void handler(int signo)
// {
//     cout << "get a signal : " << signo << endl;
//     cout << "count = " << count << endl;
//     exit(1);
// }

// int main()
// {
//     sigset_t;
//     signal(SIGALRM, handler);
//     alarm(1);
//     while (true)
//     {
//         count++;
//     }
//     return 0;
// }

// // 以下是一个使用匿名管道进行父子进程通信的示例代码。其中，父进程先创建了一个匿名管道，然后生成子进程，
// // 并关闭了管道的读取端。接着，子进程试图向已关闭的管道写入数据，导致收到SIGPIPE信号进而被终止。

// #include <stdio.h>
// #include <string.h>
// #include <unistd.h>
// #include <stdlib.h>
// #include <sys/types.h>
// #include <sys/wait.h>

// int main()
// {
//     int fd[2] = {0};
//     if (pipe(fd) < 0) // 创建匿名管道
//     {
//         perror("pipe");
//         return 1;
//     }
//     pid_t id = fork();
//     if (id == 0)
//     {
//         close(fd[0]);
//         // 子进程向管道写入数据
//         const char *msg = "I am a child process";
//         int count = 5;
//         while (count--)
//         {
//             write(fd[1], msg, strlen(msg));
//             sleep(1);
//         }
//         close(fd[1]);
//         exit(0);
//     }
//     close(fd[1]);
//     close(fd[0]); // 父进程关闭读端,会导致子进程被操作系统所杀
//     int status = 0;
//     waitpid(id, &status, 0);
//     printf("child get signal:%d\n", status & 0x7F);
//     return 0;
// }

// void handler(int signo)
// {
//     cout << "receive a signo:" << signo << endl;
// }

// int main()
// {
//     signal(6, handler);
//     while (true)
//     {
//         cout << "run..." << endl;
//         sleep(1);
//         abort();
//     }
//     return 0;
// }

// // 验证是否产生core dump标志
// int main()
// {
//     int a = 10;
//     if (fork() == 0)
//     {
//         cout << "I am a child process" << endl;
//         a /= 0;
//         exit(0);
//     }
//     int status = 0;
//     waitpid(-1, &status, 0);
//     printf("exitCode:%d  ,coreDump:%d  ,signal:%d\n", (status >> 8) & 0xff, (status >> 7) & 1, status & 0x7f);
//     return 0;
// }

// int main()
// {
//     while (true)
//     {
//         cout << "linux signal!" << endl;
//         int a=9;
//         a/=0;
//         sleep(1);
//     }
//     return 0;
// }

// void handler(int signal)
// {
//     cout << "receive a signal : " << signal << endl;
// }

// int main()
// {
//     // 这里不是调用handler方法，是设置了一个回调，当对于的SIGINT信号产生时，该方法才会被调用
//     // 若不产生该信号，则该方法不会被调用
//     // ctrl+c：本质上是给前台进程发送了2号信号，发送给目标进程，目标进程对2号信号的默认处理就是终止自己
//     // 这里对2号信号，设置了自定义的处理方法
//     signal(2, handler);
//     while (true)
//     {
//         cout << "run ..." << endl;
//         sleep(1);
//     }
//     return 0;
// }